package Fachada;

import Entidad.Usuario;
import Servicios.*;
import Singletons.Mensajes;
import VO.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import javax.mail.MessagingException;
import javax.persistence.*;
import oracle.toplink.essentials.exceptions.DatabaseException;

public class Fachada {
    private static volatile Fachada instance;

    EntityManagerFactory emf;

    //Servicios
    private ServicioReservaEstacion servReservaEstacion =  new ServicioReservaEstacion();
    private ServicioEdificio servEdificio = new ServicioEdificio();
    private ServicioUsuario servUsuario = new ServicioUsuario();
    private ServicioSuperusuario servSU = new ServicioSuperusuario();
    private ServicioAdministrador servAdmin = new ServicioAdministrador();
    private ServicioSala servSala = new ServicioSala();
    private ServicioEstacionTrabajo servET = new ServicioEstacionTrabajo();
    
    private Fachada() throws DatabaseException {
        emf = Persistence.createEntityManagerFactory("WorkStationBookerWebPU");
    }

    /**
     * <p>Método que obtiene la instancia única del Mensajes.</p>
     * @return La instancia del singleton.
     */
    public static Fachada getInstance() throws DatabaseException {
        if(instance==null)
            synchronized(Fachada.class){
                if(instance==null)
                    instance=new Fachada();
            }
        return instance;
    }

    /**
     * <p>Método de inicio de sesión de Administradores de las salas.</p>
     * @param cedula
     * @param contrasena
     * @return Boolean con el resultado de la operación.
     */
    public long iniciarSesionAdministrador(Long cedula,char[] contrasena){
        EntityManager em = emf.createEntityManager();
        long res = servAdmin.iniciarSesion(cedula, contrasena, em);
        em.close();
        return res;
    }

    /**
     * <p>Método de inicio de sesión de Súper Usuario.</p>
     * @param cedula
     * @param contrasena
     * @return Boolean con el resultado de la operación.
     */
    public boolean iniciarSesionSuperUsuario(Long cedula, char[] contrasena){
        EntityManager em = emf.createEntityManager();
        boolean res = servSU.iniciarSesion(cedula, contrasena, em);
        em.close();
        return res;
    }

    /**
     * <p>Método de inicio de sesión de los usuarios del sistema.</p>
     * @param correo
     * @param contrasena
     * @return Boolean con el resultado de la operación.
     */
    public boolean iniciarSesionUsuario(String correo, char[] contrasena){
        EntityManager em = emf.createEntityManager();
        boolean res = servUsuario.iniciarSesion(correo, contrasena, em);
        em.close();
        return res;
    }

    /**
     * <p>Se encarga del registro de un nuevo usuario</p>
     * @param usuario Usuario que se va a guardar en la base de datos
     * @return string que indica algun error en el proceso o REGISTRO_USUARIO_EXITOSO si el registro se completo correctamente
     */
    public String registrarUsuario(UsuarioVO usuario){
        EntityManager em=emf.createEntityManager();
        if(servUsuario.usuarioYaRegistrado(usuario,em)){
            em.close();
            return Mensajes.ERROR_USUARIO_EXISTE;
        }
        try{
            em.getTransaction().begin();
            servUsuario.registrarUsuario(usuario,em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
        return Mensajes.REGISTRO_USUARIO_EXITOSO;
    }

    /**
     * <p>Se encarga del registro de un nuevo administrador</p>
     * @param avo  Administrador que se va a guardar en la base de datos
     * @return string que indica algun error en el proceso o REGISTRO_USUARIO_EXITOSO si el registro se completo correctamente
     */
     public String registrarAdministrador(AdministradorVO avo){
        EntityManager em = emf.createEntityManager();
        if (servAdmin.yaExiste(avo.getCedula(), em)){
            em.close();
            return Mensajes.ERROR_ADMINISTRADOR_EXISTE;
        }
        try{
            em.getTransaction().begin();
            servAdmin.crearadmin(avo, em);
            em.getTransaction().commit();
        }catch(PersistenceException pe){
            return Mensajes.ERROR_CONEXION_BD;
        }catch (Exception e){
            return Mensajes.ERROR_INESPERADO;
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
        return  Mensajes.REGISTRO_ADMINISTRADOR_EXITOSO;

    }

    /**
     * <p>Edita la informacion del usuario pasado como argumento</p>
     * @param usuario Usuario al que se le va a editar la informacion
     * @return true si la la edicion de la informacion se completo correctamente, false de lo contrario
     */
    public void editarUsuario(UsuarioVO usuario){
        EntityManager em=emf.createEntityManager();
        try{
            em.getTransaction().begin();
            servUsuario.editarUsuario(usuario,em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
    }

    /**
     * <p>Edita la informacion del superusuario pasado como argumento</p>
     * @param superusuario SuperUsuario al que se le va a editar la informacion
     * @return true si la la edicion de la informacion se completo correctamente, false de lo contrario
     */
    public void editarSuperusuario(SuperUsuarioVO superusuario){
        EntityManager em=emf.createEntityManager();
        try{
            em.getTransaction().begin();
            servSU.editarSuperusuario(superusuario,em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
    }

    /**
     * <p>Edita la informacion del un administrador pasado como argumento</p>
     * @param avo  Administrador al cual se va a actualizar.
     * @return string Correspondiente al resultado de la transaccion.
     */
    public String editarAdministrador(AdministradorVO avo){
        EntityManager em = emf.createEntityManager();
        try{
            ServicioAdministrador sa = new ServicioAdministrador();
            em.getTransaction().begin();
            sa.actualizarAdministrador(avo,em);
            em.getTransaction().commit();
            return Mensajes.ADMINISTRADOR_ACTUALIZADO;
        }catch(PersistenceException pe){
            em.getTransaction().rollback();
            return Mensajes.ERROR_CONEXION_BD;
        }catch (Exception e){
            em.getTransaction().rollback();
            return Mensajes.ERROR_INESPERADO;
        }finally{
            em.close();
        }
    }

    /**
     * <p>busca y elimina al administrador cuya cedula corresponda al parametro cedido.</p>
     * @param cedula Parametro para la localizacion del administrador en la base de datos.
     * @return string Correespondiente al resultado de la transaccion.
     */
    public String  eliminarAdministrador (long cedula){
        EntityManager em = emf.createEntityManager();
        try {            
            ServicioAdministrador sa = new ServicioAdministrador();
            em.getTransaction().begin();
            sa.borrar(cedula, em);
            em.getTransaction().commit();
            return Mensajes.ADMINISTRADOR_BORRADO;
        } catch (PersistenceException ex) {
            em.getTransaction().rollback();
            return Mensajes.ERROR_CONEXION_BD;
        } catch (Exception ex) {
            em.getTransaction().rollback();
            return Mensajes.ERROR_INESPERADO;
        }finally{
            em.close();
        }
    }

    /**
     * <p>Busca un Administrador por cedula o por nombre</p>
     * @param cedula Parametro para la localizacion del administrador en la base de datos.
     * @param nombre Parametro para la localizacion del administrador en la base de datos.
     * @return avo AdministradorVO Correespondiente al resultado de la consulta.
     */
     public AdministradorVO leerAdministrador(String nombre,Long cedula)throws NoResultException,PersistenceException{
        EntityManager em = emf.createEntityManager();
        AdministradorVO avo;
        ServicioAdministrador sa = new ServicioAdministrador();
        avo = sa.buscar(nombre,cedula,em);
        em.close();
        return avo;
    }

    /**
     * <p>Busca un usuario que tenga un correo como el indicado</p>
     * @param correo String con el correo del usuario que se desea encontrar
     * @return usuario cuyo correo coincida con el argumento o null si no existe
     */
    public UsuarioVO leerUsuario(String correo){
        EntityManager em=emf.createEntityManager();
        ServicioUsuario servicioUsuario=new ServicioUsuario();
        UsuarioVO usuario=servicioUsuario.getUsuario(correo,em);
        em.close();
        return usuario;
    }

    /**
     * <p> Busca la lista de los edificios en la base de datos. </p>
     * @param
     * @return Retorna una lista de VO de Edificios.
     */
    public ArrayList<EdificioVO> leerEdificios(){
        EntityManager em = emf.createEntityManager();

        ArrayList<EdificioVO> ret = null;
        try {
            ret = servEdificio.listaEdificios(em);
        } catch (PersistenceException persistenceException) {
            em.close();
            return null;
        }
        em.close();
        return ret;
    }

    public boolean actualizarEdificio(EdificioVO edificio){
        EntityManager em = emf.createEntityManager();
        boolean res = false;
        try{
            em.getTransaction().begin();
            res = servEdificio.editarEdificio(edificio, em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            em.getTransaction().rollback();
            throw e;
        }catch(Exception e){
            em.getTransaction().rollback();
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            em.close();
        }
        return res;
    }

    /**
     * <p> busca una sala con el id dado </p>
     * @param idSala
     * @return Objeto con la informacion de una sala
     */
    public SalaVO leerSala(Long idSala) throws PersistenceException{
        EntityManager em = emf.createEntityManager();
        ServicioSala ss = new ServicioSala();
        SalaVO svo;
        try{
            svo = ss.leerSala(idSala,em);
        }catch(PersistenceException e){
            throw new PersistenceException(Mensajes.ERROR_CONEXION_BD);
        }
        em.close();
        return svo;
    }

    /**
     *<p> a la reserva que se le pasa como parametro le setea la hora actual
     * en el campo de hora de llegada del horario de prestamo con la hora actual</p>
     * @param rvo
     * @return Objeto con la informacion de la reserva actualizado
     */
    public ReservaEstacionVO confirmarReservacionEquipo(ReservaEstacionVO rvo){
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        ServicioReservaEstacion sre = new ServicioReservaEstacion();
        ReservaEstacionVO revo = sre.confirmarReserva(rvo,em);
        if(revo.getEstado()==Mensajes.OCUPADA){
            em.getTransaction().commit();
        }
        else{
            em.getTransaction().rollback();
        }
        em.close();
        return revo;
    }

    public ReservaSalaVO confirmarReservacionSala(ReservaSalaVO rvo){
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        ServicioReservaSala srs = new ServicioReservaSala();
        rvo = srs.ConfirmarReserva(rvo,em);
        em.getTransaction().commit();
        em.close();
        return rvo;
    }

    /**
     *  <p> crea una reserva en la base de datos con horarioReserva siendo null,
     * lo que significa que fue prestada sin reservacion, y en el campo de
     * HorarioPrestamo setea la hora actual </p>
     * @param correo
     * @param id
     * @return objeto con la informacion de la nueva reservacion (null si el usuario con ese correo no existe)
     */
    public ReservaEstacionVO prestarEstacionTrabajoSinReserva(String correo, long id){
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        ServicioEstacionTrabajo set = new ServicioEstacionTrabajo();
        ReservaEstacionVO revo = set.prestarEstacion(correo, id,em);
        if(revo==null){
            em.getTransaction().rollback();
            return null;
        }
        em.getTransaction().commit();
        em.close();
        return revo;
    }

    /**
     * <p>busca la reserva en la base de datos y le setea la hora de salida
     * del campo HorarioPrestamo con la hora actual</p>
     * <p>true: la reserva quedo actualizada en la base de datos</p>
     * <p>false:ocurrio un error al tratar de conectarse a la BD</p>
     * @param revo
     * @return boolean
     */
    public boolean devolverEstacionTrabajo (ReservaEstacionVO revo){
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        ServicioReservaEstacion sre = new ServicioReservaEstacion();
        boolean bandera = sre.finalizarReserva(revo,em);
        if(bandera){
            em.getTransaction().commit();
        }
        else{
            em.getTransaction().rollback();
        }
        em.close();
        return bandera;
    }

    public boolean devolverSala (long idReservaSala){
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        ServicioReservaSala srs = new ServicioReservaSala();
        boolean resultado = srs.devolverSala(idReservaSala,em);
        if(resultado)
            em.getTransaction().commit();
        else
            em.getTransaction().rollback();
        em.close();
        return resultado;
    }

    /**
     * <p>Hace la reservacion de una sala</p>
     * @param profesor String
     * @param horario String con el formato hh:mm-hh:mm
     * @param idAdministador Long con la cedula del administrador
     * @param idSala Long con el id de la sala
     * @param fecha Date con la fecha de la reserva
     * @return string con el resultado de la hacer la reserva de la sala
     */
    public String hacerReservacionSala(String profesor,Date fecha,String horario,long idAdministador){
        EntityManager em=emf.createEntityManager();
        ServicioReservaSala servicio=new ServicioReservaSala();
        String resultadoReservaSala;
        try{
            em.getTransaction().begin();
            resultadoReservaSala=servicio.reservarSala(profesor,fecha,horario,idAdministador,em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
        return resultadoReservaSala;
    }

    /**
     * <p>Revisa si existen reservaciones de la sala cuyo id sea el indicado,
     * el dia y a la hora indicados</p>
     * @param idSala Long con el id de la sala
     * @param fecha Date con la fecha de la reserva
     * @param horario String con el formato hh:mm-hh:mm
     * @return true si no existen reservaciones para tal fecha y hora, false si existen
     */
    public String verDisponibilidadSala(long idSala,Date fecha,String horario){
        EntityManager em=emf.createEntityManager();
        ServicioReservaSala servicio=new ServicioReservaSala();
        SalaVO salaVO;
        try{
            salaVO=servSala.leerSala(idSala,em);
            if(salaVO==null)
                throw new Exception();
        }catch(PersistenceException e){
            em.close();
            throw e;
        }catch(Exception e){
            em.close();
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }
        if(!servicio.diasMinimosReserva(fecha)){
            em.close();
            return Mensajes.ERROR_DIAS_MINIMOS_RESERVA;
        }
        if(servicio.diaDomingo(fecha.getDay()+1)){
            em.close();
            return Mensajes.ERROR_HORARIO_DOMINGO;
        }
        if(!servicio.horaPermitida(servicio.getHorario(fecha.getDay()+1,salaVO), horario)){
            em.close();
            return Mensajes.ERROR_HORARIO_ATENCION;
        }
        if(!servicio.tiempoMinimoReserva(horario)){
            em.close();
            return Mensajes.ERROR_TIEMPO_MINIMO_RESERVA;
        }
        if(!servicio.tiempoMaximoReserva(horario)){
            em.close();
            return Mensajes.ERROR_TIEMPO_MAXIMO_RESERVA;
        }
        ArrayList<ReservaSalaVO> reservasSalaVO;
        ArrayList<ReservaEstacionVO> reservasEstacionesSalaVO;
        try{
            reservasSalaVO=servicio.getReservasSala(idSala,fecha,em);
            reservasEstacionesSalaVO=servicio.getReservasEstacionSala(idSala,fecha,em);
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            em.close();
        }
        return servicio.estaDisponible(horario,reservasSalaVO,reservasEstacionesSalaVO)?Mensajes.SALA_DISPONIBLE:Mensajes.SALA_NO_DISPONIBLE;
    }

    /**
     * <p>Conduce todo el proceso de cancelacion de una reserva de sala</p>
     * @param profesor String con el nombre del profesor
     * @param horaInicio String con la hora en formato hh:mm
     * @param fecha Date
     * @return mensaje con la informacion sobre el resultado de la cancelacion
     */
    public String cancelarReservacionSala(String profesor,String horaInicio,Date fecha){
        EntityManager em=emf.createEntityManager();
        ServicioReservaSala servicio=new ServicioReservaSala();
        ReservaSalaVO reservaSala;
        try{
            reservaSala=servicio.getReservaSala(profesor,horaInicio,fecha,em);
            if(reservaSala==null)
                return Mensajes.RESERVA_SALA_NO_ENCONTRADA;
            em.getTransaction().begin();
            servicio.cancelarReservaSala(reservaSala.getId(),em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
        return Mensajes.RESERVA_SALA_ELIMINADA;
    }

    /**
     * <p> busca una estacio de trabajo con el id dado </p>
     * @param id de la estacion de trabajo que se desea encontrar
     * @return objeto con la informacion de una Estacion de Trabajo
     */
    public EstacionTrabajoVO leerEstacionTrabajo(long id){
        EntityManager em = emf.createEntityManager();
        ServicioEstacionTrabajo set = new ServicioEstacionTrabajo();
        EstacionTrabajoVO etvo = set.leerEstacionTrabajo(id,em);
        em.close();
        return etvo;
    }

    /**
     * <p> Recupera la lista de estaciones de trabajo asociadas al id de
     * sala recibido.</p>
     * @param idSala de la sala
     * @return Lista de estaciones de trabajo
     */
    public ArrayList<EstacionTrabajoVO> listaEstacionesTrabajoPorSala(long idSala){
        EntityManager em = emf.createEntityManager();
        ServicioEstacionTrabajo ser = new ServicioEstacionTrabajo();
        ArrayList<EstacionTrabajoVO> listaET = ser.listaEstacionesTrabajoPorSala(idSala,em);
        em.close();
        return listaET;
    }
    /**
     * <p>determina el estado de una estacion de trabajo en el momento en el que se llama el metodo</p>
     * @param id, fecha inicio, fecha fin
     * @return VO de reservaEstacion o null si no hay una reserva vigente
     */
    public ReservaEstacionVO verReservaEstacionTrabajo(long id, Calendar fecha, Calendar fecha2){
        EntityManager em = emf.createEntityManager();
        ServicioReservaEstacion set = new ServicioReservaEstacion();
        ReservaEstacionVO reserva = set.buscarReservaActual(id, fecha, fecha2, em);
        return reserva;
    }
    /**
     * <p> busca una sala que tenga el nombre que se le pasa a esta funcion </p>
     * @param nombre
     * @return objeto con la informacion de la sala
     */
    public SalaVO leerSalaPorNombre(String nombre){
        EntityManager em = emf.createEntityManager();
        ServicioSala sa = new ServicioSala();
        SalaVO sala = sa.buscarPorNombre(nombre,em);
        return sala;
    }
    /**
     <p>Busca una sala en especifico y cuenta el numero de administradores relativos a dicha sala.</p>
     *@param nombreSala String que guarda el nombre de la sala para realizar la busqueda.
     * @return cantidad Entero que guarda el conteo realizado del nuemero de administradores por sala.
     */
    public int numeroDeAdministradoresSala(String nombreSala) {
        EntityManager em = emf.createEntityManager();
        ServicioAdministrador sa = new ServicioAdministrador();
        int cantidad = sa.numeroDeAdministradoresPorSala(nombreSala,em);
        return cantidad;
    }
    /**
     * <p> busca una reserva de sala que este activa en el momento de llamar el metodo </p>
     * @param idSala
     * @return objeto con la informacion de una reserva de sala
     */
    public ReservaSalaVO verReservaSala(long idSala){
        EntityManager em = emf.createEntityManager();
        ServicioSala ss = new ServicioSala();
        ReservaSalaVO r = ss.buscarReservaActual(idSala,em);
        em.close();
        return r;
    }
    /**
     * <p> Actualiza los datos de una estacion en la base de datos </p>
     * @param etvo VO de la estacion con la informacion a actualizar
     * @return objeto con la informacion basica de una estacion
     */
    public EstacionTrabajoVO actualizarEstacion(EstacionTrabajoVO etvo) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        ServicioEstacionTrabajo set = new ServicioEstacionTrabajo();
        EstacionTrabajoVO vo = set.actualizarEstacion(etvo,em);
        em.getTransaction().commit();
        return vo;
    }
     public ArrayList<SalaVO> listarSalas() {
        EntityManager em = emf.createEntityManager();
        ServicioSala ss = new ServicioSala();
        return ss.listaSalas(em);
    }

    /**
     * <p>Busca y devuelve un superusuario</p>
     * @param cedula Long que contiene un numero de cedula
     * @return SuperUsuarioVO cuya cedula sea la pasada como argumento
     */
    public SuperUsuarioVO leerSuperusuario(long cedula){
        EntityManager em=emf.createEntityManager();
        SuperUsuarioVO superusuario;
        try{
            superusuario=servSU.getSuperusuario(cedula,em);
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            em.close();
        }
        return superusuario;
    }

    public ArrayList<SalaVO> leerSalas() {
        EntityManager em = emf.createEntityManager();

        ArrayList<SalaVO> ret = null;
        try {
            ret = servSala.listaSalas(em);
        } catch (PersistenceException persistenceException) {
            em.close();
            return null;
        }
        em.close();
        return ret;
    }

    public boolean actualizarSala(SalaVO sala) {
        EntityManager em = emf.createEntityManager();
        boolean res = false;
        try{
            em.getTransaction().begin();
            res = servSala.editarSala(sala, em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            em.getTransaction().rollback();
            throw e;
        }catch(Exception e){
            em.getTransaction().rollback();
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            em.close();
        }
        return res;
    }
    /**
     * <p>Revisa si existen reservaciones de la sala cuyo id sea el indicado,
     * el dia y a la hora indicados</p>
     * @param idSala Long con el id de la sala
     * @param fecha Date con la fecha de la reserva
     * @param horario String con el formato hh:mm-hh:mm
     * @return true si no existen reservaciones para tal fecha y hora, false si existen
     */
    public String verDisponibilidadEstacion(long idEstacion, long idSala, Date fecha,String horario){
        EntityManager em=emf.createEntityManager();
        ServicioReservaEstacion servRET = new ServicioReservaEstacion();
        ServicioReservaSala servRS = new ServicioReservaSala();
        EstacionTrabajoVO estacionVO = new EstacionTrabajoVO();
        SalaVO salaVO = new SalaVO();
        try{
            estacionVO = servET.leerEstacionTrabajo(idEstacion,em);
            salaVO = servSala.leerSala(idSala, em);
            if(estacionVO == null)
                throw new Exception();
        }catch(PersistenceException e){
            em.close();
            throw e;
        }catch(Exception e){
            em.close();
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }
        if(!servRET.diasMinimosReserva(fecha)){
            em.close();
            return Mensajes.ERROR_DIAS_MINIMOS_RESERVA;
        }
        if(servRET.diaDomingo(fecha.getDay()+1)){
            em.close();
            return Mensajes.ERROR_HORARIO_DOMINGO;
        }
        if(!servRS.horaPermitida(servRS.getHorario(fecha.getDay()+1,salaVO), horario)){
            em.close();
            return Mensajes.ERROR_HORARIO_ATENCION;
        }
        if(!servRET.tiempoMaximoReserva(horario)){
            em.close();
            return Mensajes.ERROR_TIEMPO_MAXIMO_RESERVA;
        }
        ArrayList<ReservaEstacionVO> reservasVO;
        try{
            reservasVO = servRET.getReservasEstacion(idEstacion, fecha, em);
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            em.close();
        }
        return servRET.estaDisponible(horario,reservasVO)?Mensajes.SALA_DISPONIBLE:Mensajes.SALA_NO_DISPONIBLE;
    }
    /**
     * <p> lee el archivo de configuracion y lo trasforma a un formato
     * que el sistema entienda</p>
     * @return arreglo de String
     * @throws FileNotFoundException
     */
    public String[] leerArchivo() {
        try {
            return ServicioSuperusuario.verArchivo();
        } catch (IOException ex) {
            return null;
        }
    }
    /**
     * <p> verifica que las restricciones esten dentro de los
     * rangos permitidos</p>
     * @param datos
     * @return <p>informacion del dato que incumple la restriccion
     * o null si todos los datos son validos</p>
     */
    public String validarRestricciones(int[] datos) {
        String res = ServicioSuperusuario.validarRestricciones(datos);
        return res;
    }

    public boolean actualizarArchivo(int[] datos) {
        boolean res;
        ServicioSuperusuario ss = new ServicioSuperusuario();
        try {
            res = ss.actualizarArchivo(datos);
        } catch (IOException ex) {
            return false;
        }
        return res;
    }

    public AdministradorVO[] listaAdministradores() {
        EntityManager em=emf.createEntityManager();
        AdministradorVO [] listaAvos = servAdmin.listaAdministradores(em);
        em.close();
        return listaAvos;
    }

    /**
     * <p>Recopila informacion de interes de las reservas de estacion definidas para el siguiente dia
     * y envia un correo de recordatorio a los usuarios correspondientes</p>
     * @throws MessagingException cuando hay algun problema enviando los correos
     */
    public void notificarUsuariosConReserva() throws MessagingException {
        EntityManager em=emf.createEntityManager();
        ServicioReservaEstacion servicio=new ServicioReservaEstacion();
        try{
            ArrayList<String[]> informacion=servicio.getInformacionReservas(em);
            servicio.enviarCorreo(informacion);
        }catch(PersistenceException e){
            throw e;
        }catch(MessagingException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally {
            em.close();
        }
    }

    public String validarHoras(String horario, int horaInicio, int horaFin, int minInicio, int minFin) {
        ValidacionDatosEntrada vde = new ValidacionDatosEntrada();
        String res = vde.validarHoras(horario, horaInicio, horaFin, minInicio, minFin);
        return res;
    }

    public boolean validarFechaReservaEstacion(Calendar fecha) {
        ValidacionDatosEntrada vde = new ValidacionDatosEntrada();
        boolean res = vde.validarFechaReservaEstacion(fecha);
        return res;
    }

    public ReservaEstacionVO reservarEstacionTrabajo(UsuarioVO usuario, long id, String horario, Date fecha) {
        ServicioReservaEstacion sre = new ServicioReservaEstacion();
        ReservaEstacionVO rvo=null;
        EntityManager em = emf.createEntityManager();
        try{
            em.getTransaction().begin();
            rvo = sre.reservarEstacion(usuario, id, horario,fecha,em);
            em.getTransaction().commit();
        }catch(Exception e){
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
        }finally{
            if(em.isOpen())
                em.close();
        }
        return rvo;
    }



    public ReservaExtendidaVO[] listaReservasUsuario(UsuarioVO usuario) {
        EntityManager em = emf.createEntityManager();
        ReservaExtendidaVO [] listaReservas = servReservaEstacion.listaReservasUsuario(em,usuario);
        em.close();
        return listaReservas;
    }

    public String cancelarReservacionSalaUsuario(long id) {
        EntityManager em = emf.createEntityManager();
        String mensaje="";
        ReservaEstacionVO revoEstacion;
        try{
            revoEstacion=servReservaEstacion.buscar(id, em);
            if(revoEstacion==null)
                return Mensajes.RESERVA_ESTACION_NO_ENCONTRADA;
            em.getTransaction().begin();
            servReservaEstacion.cancelarReservaUsuario(id,em);
            em.getTransaction().commit();
        }catch(PersistenceException e){
            throw e;
        }catch(Exception e){
            throw new PersistenceException(Mensajes.ERROR_ENTITY_MANAGER);
        }finally{
            if(em.getTransaction().isActive())
                em.getTransaction().rollback();
            em.close();
        }
        return Mensajes.RESERVA_ESTACION_ELIMINADA;
    }

    /**
     * <p>Devuelve la hora actual con el formato hh:mm, devuelve
     * la hora con el desfase enviado como parámetro.</p>
     * @param numeroHorasDesfase
     * @return hora actual con formato hh:mm
     */
    public String horaActual(int numeroHorasDesfase) {
        return ServicioReservaEstacion.horaActual(numeroHorasDesfase);
    }

    public boolean horarioAtencion(String horarioAtencion,String horarioSolicitud){
        ServicioReservaSala servicio=new ServicioReservaSala();
        return servicio.horaPermitida(horarioAtencion, horarioSolicitud);
    }

    public ReservaSalaVO[] listaReservasSala(Long idSala) {
        EntityManager em = emf.createEntityManager();
        ReservaSalaVO [] listaReservas = servReservaEstacion.listaReservasSala(em,idSala);
        em.close();
        return listaReservas;
    }

}
